#ifndef __ENCODER_H_
#define __ENCODER_H_

#include "driver/pulse_cnt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/spi_master.h"
class Encoder_Base {
    public:
    Encoder_Base() {
        on_reach_task_handle = nullptr;
    }
    ~Encoder_Base() {}
    int init(int a_pin, int b_pin);
    

    int run(bool need_watch);
    int stop(void);
    int clear(void);
    int get_pulse_count(void);
    int destroy(void);

    public: // data

    pcnt_unit_handle_t pcnt_unit_handle;
    pcnt_channel_handle_t pcnt_chan_a_handle;
    pcnt_channel_handle_t pcnt_chan_b_handle;
    QueueHandle_t queue_handle;
    TaskHandle_t on_reach_task_handle;
    int pluse_count;

    typedef struct {
        uint8_t type; // 0 stop, other watch value
        int event_value;
    } on_reach_push_msg_t;
    
    private:
    

    private: // static
    static bool pcnt_on_reach_callback(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx);
    static void pcnt_on_reach_task(void *argv);
};

class Encoder_MT6701 : Encoder_Base {
    public: // data
    typedef union {
        struct
        {
            uint32_t crc : 6;
            uint32_t status : 4;
            uint32_t angle_data : 14;
            uint32_t rsv : 8;
        };
        uint32_t data;
    } mt6701_raw_data_t;

    typedef struct {
        uint8_t filed_status;
        uint16_t raw_code;
        float raw_angle;
        float full_angle;
        float last_angle; 
        int32_t rotation_count;
    } mt6701_angle_data_t;

    public:
    Encoder_MT6701() {}
    ~Encoder_MT6701() {}
    int init(int spi_bus, int spi_sck, int spi_miso, int cs_pin);
    void run();

    int IRAM_ATTR raw_code_read(mt6701_raw_data_t *data);
    uint16_t IRAM_ATTR raw_code_read(void);
    int IRAM_ATTR read(mt6701_angle_data_t *data);

    
    uint8_t crc6(uint8_t *data, uint8_t length);
    private:
    spi_host_device_t m_spi_bus;
    spi_device_handle_t m_spi_dev;
    mt6701_angle_data_t angle_data;
    int m_cs_pin; 
};

#endif // __ENCODER_H_

